package il.ac.mta.javaweb.ex1.ui;

import il.ac.mta.javaweb.ex1.logic.*;
import il.ac.mta.javaweb.ex1.logic.grids.BattleShipsGrid;
import il.ac.mta.javaweb.ex1.logic.players.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import javax.swing.text.html.HTMLDocument.Iterator;


//TODO: ALON, I followed the below structure while working with the Game class
//      I tried to passed players by reference from the gameLoop() function to other function... I hope I got it right.
//TODO: PlayerBase needs 2 more methods, isActive()  and   isHuman()   Thank you.
/*
Game - class
	players - array of class PlayerBase
		selfGrid
		markGrid
		Name
*/

public class UIGame {
	
	Game myGame = null;  // TODO: need to import the Game class
	static BufferedReader stdin;
	static int totalSubsPerPlayer = 5;
	static int gridSize = 10;
	
	public UIGame(Game theGame) {
		
		myGame = theGame;
		stdin = new BufferedReader (new InputStreamReader(System.in));
		addEmptyAttackGrids();
		gameLoop();
	}

	////////////////////////////////////////////////////////////////////////////
	
	private static void gameLoop() throws IOException  {
		
		boolean isWin = false;
		boolean selectAgainFlag;
		boolean isPlayerHuman;
		int currentPlayerIndex = -1;
		int playerToAttackIndex = -1;
		int index = 0;

		
		// Loop over all players
		while (isWin == false) {
			
			index++;
			if (index == myGame.players.length)
			
			// Get current player index in the array
			currentPlayerIndex = index;
			
			// Check if the current player is human
			isPlayerHuman = myGame.players[currentIndex].isHuman; //TODO: each player needs a "isHuman" method
			
			if (isPlayerHuman) { 
				
				// Loop to allow the same player endless markings
				selectAgainFlag = true;
				while (selectAgainFlag == true) {
					
					playerToAttackIndex = runSelectPlayerToAttack(myGame.players[currentPlayerIndex]);
					// TODO: use selection to display the relevant ATTACK GRID
					if (runAttackMenu(myGame.players[currentPlayerIndex], myGame.players[playerToAttackIndex]) == true) {
						selectAgainFlag = true;
						continue;
					}
					else {
						selectAgainFlag = false;
					}
				}
			}
			// This is a CPU player
			else {
				//TODO: call function to GET random player to attack
				//TODO: call function to GET random cell to attack
				//TODO: call function to Bomb the selected ATTACK player in the selected cell
			}
			
			//TODO: call a function to CHECK if we have a winner (isWin true/false)
		}
		
		System.out.println("");
		System.out.println("GAME OVER");
		System.out.println("Winner: " + myGame.players[currentPlayerIndex].getName());
		System.out.println("");
	}
	
	////////////////////////////////////////////////////////////////////////////
	
	private static void addEmptyAttackGrids()  { 
		
		//TODO: loop over all players in the myGame and add attack grid for each other players
		
	}
	
	////////////////////////////////////////////////////////////////////////////
	
	private static int runSelectPlayerToAttack(PlayerBase currentPlayer) throws IOException  {
		
		boolean keepRunning = true;
		String playerToAttackStr = "";
		int playerToAttackIndex = -1;
		
		while (keepRunning) {
			
			displayListOfActivePlayers();
			
			runSelectPlayerToAttack(currentPlayer);
			
			// verify input player to attack is valid
			playerToAttackStr = stdin.readLine();
			if (playerToAttackStr == currentPlayer.getName()) {
				System.out.println("You can't select this player to attack, try again.");
				continue;
			}
			
			boolean attackOnListFlag = false;
			for (int i=0; i<myGame.players.length; i++) {
				if (myGame.players[i].isActive() == true) {  //TODO: each player needs an "isActive()" method
					if (playerToAttackStr == myGame.players[i].getName()) {
						attackOnListFlag = true;
						playerToAttackIndex = i;
						break;
					}
				}
			}
			
			if (attackOnListFlag == false) {
				System.out.println("No such player `"+ playerToAttackStr +"`, try again.");
			}
			else {
				keepRunning = false;
			}
		}

		// We now have a valid player we can attack!
		return playerToAttackIndex;
	}

	private static void printSelectPlayerToAttack() {
		
		System.out.println("Please write the name of the player you would like to attack: "); 
	}
	
	////////////////////////////////////////////////////////////////////////////
		
	private static void displayListOfActivePlayers() {
		
		PlayerBase[] listOfPlayers = myGame.players;
		
		for (int i=0; i<listOfPlayers.length; i++) {
			if (listOfPlayers[i].isActive() == true) {
				
				System.out.print(listOfPlayers[i].getName());
				if (i<listOfPlayers.length-1) {
					System.out.print(", ");
				}
				else {
					System.out.print(".");
				}
				System.out.println("");
			}
		}
	}
	
	////////////////////////////////////////////////////////////////////////////
	
	private static boolean runAttackMenu(PlayerBase player, PlayerBase playerToAttack) throws IOException  {
		boolean keepRunning = true;
		String inOption = "";
		boolean selectAgainFlag;
		
		while (keepRunning) {

			printAttackMenu(player.getName());
			inOption = stdin.readLine();
			
			if ((inOption == "1") || (inOption == "2") || (inOption == "3")
				|| (inOption == "B") || (inOption == "b")) {
				
				keepRunning = true;
			}
		}
		
		if (inOption == "1") {
			runMarkCellMenu(player, playerToAttack);
			selectAgainFlag = true;
		}
		else if (inOption == "2") {
			runCancelMarkCellMenu(player, playerToAttack);
			selectAgainFlag = true;
		}
		else if (inOption == "3") {
			runBombPlayerMenu(player, playerToAttack);
			selectAgainFlag = false;
		}
		else if ((inOption == "B") || (inOption == "b")) {
			return true; // back, and select a different player to attack
		}
		
		return selectAgainFlag; 
	}

	 private static void printAttackMenu(String playerName) {
		
		System.out.println(playerName + ", please select your move:");
		System.out.println("");
		System.out.println("1. Mark cell.");
		System.out.println("2. Cancel marked cell.");
		System.out.println("3. Bombs away...");
		System.out.println("B. Attack different player.");
	 }
	 
	 ////////////////////////////////////////////////////////////////////////////

	 private static void runMarkCellMenu(PlayerBase player, PlayerBase playerToAttack) throws IOException  {

		 boolean keepRunning = true;
		 String inOption = "";
		 
		 while (keepRunning) {
			 
			 printMarkCellMenu();
			 inOption = stdin.readLine();
			 
			 if (inOption.length() == 2) {
				 
				 inOption = inOption.toLowerCase();
				 int posIntLetter = (int) inOption.charAt(0) - 97;
				 int posIntNum = (int) inOption.charAt(1) - 48;
				 
				 if ((posIntLetter < 0) || (posIntLetter > 9)) {
					continue;
				 }
			 	 if ((posIntNum < 0) || (posIntNum > 9)) {
			 		continue;
	 			 }
			 	 
			 	 // input is valid
			 	 keepRunning = false;

			 	 // TODO: execute the marking on the specified grid, not sure how to call it - NEED Alon (use posIntLetter & posIntNum)
			 }
		 }
	 }

	 private static void printMarkCellMenu() {

		 System.out.println("Please select a cell to mark in the following format (example: A0)");
	 }
	 
	 ////////////////////////////////////////////////////////////////////////////
	 
	 private static void runCancelMarkCellMenu(PlayerBase player, PlayerBase playerToAttack) throws IOException  {

		 boolean keepRunning = true;
		 String inOption = "";
		 
		 while (keepRunning) {
			 
			 printCancelMarkCellMenu();
			 inOption = stdin.readLine();
			 
			 if (inOption.length() == 2) {
				 
				 inOption = inOption.toLowerCase();
				 int posIntLetter = (int) inOption.charAt(0) - 97;
				 int posIntNum = (int) inOption.charAt(1) - 48;
				 
				 if ((posIntLetter < 0) || (posIntLetter > 9)) {
					continue;
				 }
			 	 if ((posIntNum < 0) || (posIntNum > 9)) {
			 		continue;
	 			 }
			 	 
			 	 // input is valid
			 	 keepRunning = false;

			 	 // TODO: execute the cancel marking on the specified grid, not sure how to call it - NEED Alon (use posIntLetter & posIntNum)
			 }
		 }
	 }

	 private static void printCancelMarkCellMenu() {

		 System.out.println("Please select a cell cancel the mark in the following format (example: A0)");
	 }

	////////////////////////////////////////////////////////////////////////////

	 private static void runBombPlayerMenu(PlayerBase player, PlayerBase playerToAttack) throws IOException  {
		 
		 boolean keepRunning = true;
		 String inOption = "";
		 
		 while (keepRunning) {
			 
			 printBombPlayerMenu();
			 inOption = stdin.readLine();
			 
			 if (inOption.length() == 2) {
				 
				 inOption = inOption.toLowerCase();
				 int posIntLetter = (int) inOption.charAt(0) - 97;
				 int posIntNum = (int) inOption.charAt(1) - 48;
				 
				 if ((posIntLetter < 0) || (posIntLetter > 9)) {
					continue;
				 }
			 	 if ((posIntNum < 0) || (posIntNum > 9)) {
			 		continue;
	 			 }
			 	 
			 	 // input is valid
			 	 keepRunning = false;

			 	 // TODO: execute the bombing of the cell on the specified grid, not sure how to call it - NEED Alon
			 	 // use posIntLetter  &   posIntNum
			 }
		 }
	}

	private static void printBombPlayerMenu() {
		
		System.out.println("Please select a cell to attack in the following format (example: A0)");
	}
}
